﻿using System;
using System.Data;
using System.Data.SqlClient;
using System.Web.UI;
using System.Web.Configuration;

namespace AJAX_learning.Chapter11
{
	public partial class AsyncDataReaderPageAaspx : Page
	{
		protected override void OnLoad(EventArgs e)
		{
			base.OnLoad(e);
			// Register the asynchronous methods for later use.
			// This method returns immediately.
			Page.AddOnPreRenderCompleteAsync(BeginTask, EndTask);
		}

		// Perform the data binding in the next stage of the page lifecycle.
		protected override void OnPreRenderComplete(EventArgs e)
		{
			base.OnPreRenderComplete(e);

			grid.DataSource = _table;
			grid.DataBind();
		}

		// Make sure the connection is closed in the event of an error.
		public override void Dispose()
		{
			if (_con != null) _con.Close();
			base.Dispose();
		}

		// The ADO.NET objects need to be accessible in several different
		// event handlers, so they must be declared as member variables.
		private SqlConnection _con;
		private SqlCommand _cmd;
		private DataTable _table;

		private IAsyncResult BeginTask(object sender, EventArgs e, AsyncCallback cb, object state)
		{
			// Check the cache.
			if (Cache["Employees"] != null)
			{
				return new CompletedSyncResult((DataTable)Cache["Employees"], cb, state);
			}

			// Create the command.
			string connectionString = WebConfigurationManager.ConnectionStrings["NorthwindAsync"].ConnectionString;
			_con = new SqlConnection(connectionString);
			_cmd = new SqlCommand("SELECT * FROM Employees", _con);

			// Open the connection.
			// This part is not asynchronous yet.
			try
			{
				_con.Open();
			}
			catch (Exception err)
			{
				return new CompletedSyncResult(err, cb, state);
			}

			// Run the query asynchronously.
			// This method returns immediately and provides ASP.NET
			// with the IAsyncResult object it needs to track progress.
			return _cmd.BeginExecuteReader(cb, state);
		}

		// This method fires when IAsyncResult indicates the task is complete.
		private void EndTask(IAsyncResult ar)
		{
			CompletedSyncResult completedSync = ar as CompletedSyncResult;
			if (completedSync != null)
			{
				try
				{
					_table = completedSync.Result;
					lblError.Text = "Completed with data from the cache.";
				}
				catch (Exception err)
				{
					lblError.Text = "A connection error occurred.";
				}
			}
			else
			{
				try
				{
					SqlDataReader reader = _cmd.EndExecuteReader(ar);

					_table = new DataTable("Employees");
					_table.Load(reader);
					Cache.Insert("Employees", _table, null, DateTime.Now.AddMinutes(5), TimeSpan.Zero);
				}
				catch (SqlException err)
				{
					lblError.Text = "The query failed.";
				}
			}
		}
	}
}